package database;

import database.domain.ColumnInfo;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * Description: database meta infomation
 * Created by E440 on 2017/5/18.
 */
public class UtilDatabaseMetaInfo {

    /** 获取table name 组成的set,connection 在本函数内关闭
     * @param connection
     * @return
     * @throws SQLException
     */
    static public Set<String> getTableSet(Connection connection) throws SQLException {
        Set<String> tableSet=new HashSet<>();
        DatabaseMetaData dbmd = connection.getMetaData();

        ResultSet rs=null;
        /**
         * catalog 类别名称
         * schemaPattern 用户方案模式，
         * tableNamePattern 表
         * types 类型
         * 获取所有表
         * dbmd.getTables(catalog, schemaPattern, tableNamePattern, types)
         */
        try {
            rs = dbmd.getTables(null, null, null, new String[]{"TABLE"});//参数列表 1:类别名称,2: 模式名称的模式,3:表名称模式,4:要包括的表类型所组成的列表

            while(rs.next()){
                tableSet.add(rs.getString(3));
            }
        }finally {
           UtilJdbc.free(rs,null,null);
        }
        return tableSet;
    }

    static public Map<String,ColumnInfo> getColumnInfoMap(Connection con,String tableName) throws SQLException {
        String cataLogName=con.getCatalog();
        DatabaseMetaData dbmd = con.getMetaData();
        ResultSet rs=null;
        Map<String,ColumnInfo> map=new HashMap<>();
        /**
         * catalog 类别名称
         * schemaPattern 用户方案，模式
         * tableNamePattern 表
         * columnNamePattern 列
         * 获取表的列信息
         * dbmd.getColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern)
         */
        try{
            rs = dbmd.getColumns(cataLogName, null, tableName, null);
            while(rs.next()) {
                /**
                 * 所有列如下：
                 * TABLE_CAT String => 表类别（可为 null）
                 TABLE_SCHEM String => 表模式（可为 null）
                 TABLE_NAME String => 表名称
                 COLUMN_NAME String => 列名称
                 DATA_TYPE int => 来自 java.sql.Types 的 SQL 类型
                 TYPE_NAME String => 数据源依赖的类型名称，对于 UDT，该类型名称是完全限定的
                 COLUMN_SIZE int => 列的大小。
                 BUFFER_LENGTH 未被使用。
                 DECIMAL_DIGITS int => 小数部分的位数。对于 DECIMAL_DIGITS 不适用的数据类型，则返回 Null。
                 NUM_PREC_RADIX int => 基数（通常为 10 或 2）
                 NULLABLE int => 是否允许使用 NULL。
                 columnNoNulls - 可能不允许使用 NULL 值
                 columnNullable - 明确允许使用 NULL 值
                 columnNullableUnknown - 不知道是否可使用 null
                 REMARKS String => 描述列的注释（可为 null）
                 COLUMN_DEF String => 该列的默认值，当值在单引号内时应被解释为一个字符串（可为 null）
                 SQL_DATA_TYPE int => 未使用
                 SQL_DATETIME_SUB int => 未使用
                 CHAR_OCTET_LENGTH int => 对于 char 类型，该长度是列中的最大字节数
                 ORDINAL_POSITION int => 表中的列的索引（从 1 开始）
                 IS_NULLABLE String => ISO 规则用于确定列是否包括 null。
                 YES --- 如果参数可以包括 NULL
                 NO --- 如果参数不可以包括 NULL
                 空字符串 --- 如果不知道参数是否可以包括 null
                 SCOPE_CATLOG String => 表的类别，它是引用属性的作用域（如果 DATA_TYPE 不是 REF，则为 null）
                 SCOPE_SCHEMA String => 表的模式，它是引用属性的作用域（如果 DATA_TYPE 不是 REF，则为 null）
                 SCOPE_TABLE String => 表名称，它是引用属性的作用域（如果 DATA_TYPE 不是 REF，则为 null）
                 SOURCE_DATA_TYPE short => 不同类型或用户生成 Ref 类型、来自 java.sql.Types 的 SQL 类型的源类型（如果 DATA_TYPE 不是 DISTINCT 或用户生成的 REF，则为 null）
                 IS_AUTOINCREMENT String => 指示此列是否自动增加
                 YES --- 如果该列自动增加
                 NO --- 如果该列不自动增加
                 空字符串 --- 如果不能确定该列是否是自动增加参数

                 */
               /* System.out.println(rs.getString("COLUMN_NAME") + " 类型=" + rs.getInt("DATA_TYPE") + " 列大小=" + rs.getInt("COLUMN_SIZE") +
                        " 注释=" + rs.getString("REMARKS") +
                        " 是否允许为NULL=" + rs.getInt("NULLABLE"));*/
                String columnName=rs.getString("COLUMN_NAME");
                int typeInt=rs.getInt("DATA_TYPE");
                String typeName=rs.getString("COLUMN_NAME");
                int columnSize=rs.getInt("COLUMN_SIZE");
                int decimalDigits=rs.getInt("DECIMAL_DIGITS");
                boolean nullAble=rs.getInt("NULLABLE")==0?false:true;
                String remark=rs.getString("REMARKS");

                ColumnInfo columnInfo=new ColumnInfo(columnName,typeInt,typeName,columnSize,decimalDigits,nullAble,remark);
                map.put(columnName,columnInfo);
            }
        }finally {
            UtilJdbc.free(rs,null,null);
        }
        return map;
    }
}
